/*
 * ControladorR14Productor.h
 *
 *  Created on: Dec 1, 2013
 *      Author: m
 */

#ifndef CONTROLADORR14PRODUCTOR_H_
#define CONTROLADORR14PRODUCTOR_H_

#include "DefinicionesComunes.h"
#include "ICinta15.h"
#include "IRobot14.h"
#include "IRobot16.h"

#include "Cinta15.h"
#include "Robot14Productor.h"
#include "Robot16Consumidor.h"
#include "../../../middleware/CommunicationRobot16.h"
#include "DSMManager.h"

class ControladorR14Productor :
        public ICinta15, public IRobot14, public IRobot16
{
protected:
    Cinta15 m_cinta15;
    Robot14Productor  m_robot14;
    Robot16Consumidor m_robot16;
    //middleware::CommunicationRobot16 m_comRobot16;
    bool m_tomarCinta;

public:
    ControladorR14Productor() :
        m_tomarCinta( true )
    {
        DSMManager::inicializar( "robot14pro" );
    }

    virtual ~ControladorR14Productor()
    {
    }

    bool c15_depositar( const ElementoProduccion &e )
    {
        bool depositoOk;

        m_cinta15.iniciarExclusionMutua();

        if ( m_tomarCinta )
        {
            m_tomarCinta = false;

            // Antes de utilizar la cinta debo verificar que no la este
            //  usando el otro robot. En ese caso me quedo esperando que
            //  termine de usarla.

            if ( m_cinta15.getCinta()->consumidorUsando() )
            {
                m_cinta15.getCinta()->setProductorEsperando( true );

                m_cinta15.terminarExclusionMutua();

                m_cinta15.dormirProductor();

                m_cinta15.iniciarExclusionMutua();
            }
            else
            {
                m_cinta15.getCinta()->setProductorUsando( true );
            }
        }

        depositoOk = m_cinta15.getCinta()->depositar( e );

        m_cinta15.terminarExclusionMutua();

        return depositoOk;
    }

    bool c15_avanzar()
    {
        bool avanzoOk;

        m_cinta15.iniciarExclusionMutua();

        avanzoOk = m_cinta15.getCinta()->avanzar();

        m_cinta15.terminarExclusionMutua();

        return avanzoOk;
    }

    void r14_esperarEspacioVacio()
    {
        // Actualizo el estado del robot11

        m_robot14.iniciarExclusionMutua();

        m_robot14.setEsperaEspacio( true );

        m_robot14.terminarExclusionMutua();

        // Libero la cinta
        m_tomarCinta = true;

        m_cinta15.iniciarExclusionMutua();

        m_cinta15.getCinta()->setProductorUsando( false );

        // Reviso si el consumidor estaba esperando, si es asi lo despierto

        if ( m_cinta15.getCinta()->consumidorEsperando() )
        {
            m_cinta15.getCinta()->setConsumidorEsperando( false );

            m_cinta15.getCinta()->setConsumidorUsando( true );

            m_cinta15.despertarConsumidor();
        }

        m_cinta15.terminarExclusionMutua();

        // Duermo
        m_robot14.dormir();
    }

    void r16_notificarNuevoElemento()
    {
        bool esperaProducto;

        m_robot16.iniciarExclusionMutua();

        if ( m_robot16.esperaProducto() )
        {
            m_robot16.setEsperaProducto( false );

            m_robot16.despertar();
        }

        m_robot16.terminarExclusionMutua();


        // Indico que ya no voy a utilizar más la cinta

        m_cinta15.iniciarExclusionMutua();

        m_cinta15.getCinta()->setProductorUsando( false );

        // Reviso si el consumidor estaba esperando, si es asi lo despierto

        if ( m_cinta15.getCinta()->consumidorEsperando() )
        {
            m_cinta15.getCinta()->setConsumidorEsperando( false );

            m_cinta15.getCinta()->setConsumidorUsando( true );

            m_cinta15.despertarConsumidor();
        }

        m_cinta15.terminarExclusionMutua();

        // TODO: Descomentar para combinar con lo de alex!
        //m_comRobot16.notificarNuevoProducto();
    }






    int c15_contarElementos()
    {
        throw Exception("Metodo no implementado");
    }

    bool c15_tieneElementos()
    {
        throw Exception("Metodo no implementado");
    }

    ElementoProduccion c15_quitar()
    {
        throw Exception("Metodo no implementado");
    }

    bool r14_esperaEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_notificarEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_notificarQuiteElemento()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_notificarNuevoElemento()
    {
        throw Exception("Metodo no implementado");
    }

    void r14_esperarNuevoElemento()
    {
        throw Exception("Metodo no implementado");
    }

    void r16_esperarNuevoElemento()
    {
        throw Exception("Metodo no implementado");
    }

    void r16_esperarEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    bool r16_esperaEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r16_notificarEspacioVacio()
    {
        throw Exception("Metodo no implementado");
    }

    void r16_notificarQuiteElemento()
    {
        throw Exception("Metodo no implementado");
    }
};

#endif /* CONTROLADORR14PRODUCTOR_H_ */
